home *** CD-ROM | disk | FTP | other *** search
-
- /*
- EGSFlick - Play .FLI/.FLC animations under EGS
- Frank Neumann, November 1993
-
- This program plays .FLI (fixed to 320x200) or .FLC (any
- resolution) anim files in an EGS window on a graphic board
- that is capable of producing an 8 bit, CLUT-based chunky pixel
- display. This is true for most currently available Amiga graphic
- boards, such as the Rainbow III, Piccolo, Spectrum and maybe
- others that are still to come.
-
- History:
- V1.0 24.03.1993 First version, already stable, but not to
- be released for a long time.
-
- V1.1 14.11.1993 Thought it would be a good idea to release this
- goodie - as EGS seems to become more and more
- used around the world. First release.
- V1.1a 19.11.1993 Removed the Map->Type test of the EScreen - seems
- I have not yet understood some of EGS' concepts..
-
- V1.2 13.09.1994 After a long break, a small addition: Now listens
- to the environment variable 'EGSFLICK' which
- determines another screen mode than the default.
-
- This code is mostly based on xflick for X11 systems. What follows is
- the original comment:
-
- xflick - Ron Schnell, March, 1991
-
- This code is provided as is, with no warrantees, expressed
- or implied. I believe this code to be free of encumbrance,
- and offer it to the public domain. I ask, however, that
- this paragraph and my name be retained in any modified
- versions of the file you may make, and that you notify me
- of any improvements you make to the code.
-
- Ron Schnell (ronnie@sos.com)
-
- The following changes are from Michael Pall
- (pall@rz.uni-karlsruhe.de) Mar 25-28 1991:
-
- Lots of bugfixes and changes to the structure of the files.
- The file is interpreted before we display it.
- Moved the interpretation part to read.c.
- We use Pixmaps and/or XImages.
- Added interactive input to change the speed/single step.
-
- The following extensions are from Klaus Ehrenfried
- (klaus@spock.es.go.dlr.de) Oct 23-24 1992:
-
- Add handling of FLI_DELTA and FLI_256_COLOR chunks.
- Recognize magic number FLC_MAGIC = 0xaf12 for newer
- flic files.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/signal.h>
- #include <sys/time.h>
- #include "eflick.h"
-
- #include <exec/types.h>
- #include <clib/exec_protos.h>
- #include <egs/egsintui.h>
- #include <egs/clib/egsintui_protos.h>
- #include <egs/egsgfx.h>
- #include <egs/clib/egsgfx_protos.h>
- #include <egs/egs.h>
- #include <egs/clib/egs_protos.h>
-
- /* Amiga version identification */
- static char *version = "$VER: EGSFlick 1.2 (13.09.94)";
-
- int verbose = 0;
- static int jiffies;
-
- /* pointers to required libraries */
- struct Library *EGSIntuiBase = NULL;
- struct Library *EGSBase = NULL;
- struct Library *EGSGfxBase = NULL;
- struct Library *EGSBlitBase = NULL;
-
- struct EI_NewScreen newscreen = {
- NULL, /* screenmode name is put here later... */
- 8, 0, "EGSFlick Screen", /* depth, pad, title */
- NULL, /* CLUPtr */
- { 3, 1, 0, 2, 1, 3, 1 }, /* WinColors */
- 0, /* backPen */
- NULL, /* backPattern */
- NULL, /* Maus */
- NULL /* TextAttr */
- };
-
-
- static struct EI_NewWindow newWindow =
- {
- 50, 30, 10, 10, /* LeftEdge, TopEdge, Width, Height */
- 0, 0, 0, 0, /* MinWidth,MinHeight, MaxWidth, MaxHeight */
- NULL, /* Screen - might be set to some screen later */
- EI_WINDOWCLOSE | EI_WINDOWBACK | EI_WINDOWDRAG, /* SysGadgets */
- NULL, /* FirstGadgets */
- "EGSFlick V1.2 by Franky", /* Title */
- EI_SMART_REFRESH | EI_GIMMEZEROZERO | EI_WINDOWACTIVE, /* Flags */
- EI_iCLOSEWINDOW | EI_iVANILLAKEY | EI_iACTIVEWINDOW | EI_iINACTIVEWINDOW, /*EI_IDCMPFlags */
- NULL, /*Port */
- {0,0,0,0,0,0,0}, /* Colors */
- NULL, /* Menu */
- NULL /* Render */
- };
-
- EI_ScreenPtr screen = NULL;
- EI_WindowPtr window = NULL;
- E_EBitMapPtr map = NULL;
- EG_RastPortPtr rp;
- E_CLU oldscreencolors[MAXCOL], screencolors[MAXCOL];
-
- static flag_noint = 0; /* Don't interpret file first */
-
- static int fdelay; /* Frame delay */
- static int wwidth, wheight; /* Width and height of the window */
-
- char fliname[256];
-
- /* a modified XColor structure definition */
- typedef struct {
- unsigned long pixel;
- unsigned char red, green, blue;
- } XColor;
-
-
- /* The structure to hold the elements of the interpreted display list */
-
- struct disp_list
- {
- int disp_type;
- int disp_frame;
- E_EBitMapPtr disp_pix;
- XColor *disp_cols;
- int disp_numcol;
- int disp_width, disp_height;
- int disp_destx, disp_desty;
- struct disp_list *disp_next;
- };
-
- static struct disp_list disp_root; /* The start of the display list */
- static struct disp_list *disp_cur; /* The current position */
-
- extern void interpret_fli();
-
- /* prototypes */
- void Crash( char * );
-
-
- /* Convert the frame delay to microseconds/seconds */
- static void
- convert_fdelay()
- {
- jiffies = (fdelay * 70) / 50;
-
- }
-
-
- /* Print a usage message and exit */
- static void
- usage()
- {
- (void) fprintf(stderr,
- "Usage: EGSFlick [-v] [-r<count>] [-d<delay>] [-n] fli_file\n");
- (void) fprintf(stderr, " -v Verbose Debugging info\n\
- -r<count> Repeat count times (0 = loop forever)\n\
- -d<delay> Delay between frames in 1/70s\n\
- -n Don't interpret file before display \
- (slower but uses less memory)\n");
- exit(0);
- }
-
-
- /* Check for pending EI_iVANILLAKEY messages and process them */
- static void
- check_key()
- {
- struct EI_EIntuiMsg *msg;
-
- static int stepflag = 0; /* Default: singlestep is off */
-
- int onestep = stepflag; /* 1 if we should be loop waiting for a step */
-
- while (NULL != (msg = (struct EI_EIntuiMsg *)GetMsg(window->UserPort)) || onestep)
- {
- if (msg != NULL)
- {
- switch (msg->Class)
- {
- case EI_iVANILLAKEY:
- switch (msg->Code)
- {
- /* Minus: Slow down */
- case '-':
- fdelay++;
- convert_fdelay();
- break;
-
- /* Plus: Speed up */
- case '+':
- if (fdelay)
- fdelay--;
- convert_fdelay();
- break;
-
- /* Space: Single step */
- case ' ':
- stepflag = 1;
- onestep = 0;
- break;
-
- /* c: Continue animation */
- case 'c':
- stepflag = 0;
- onestep = 0;
- break;
-
- /* 'q': Quit */
- case 'q':
- ReplyMsg(msg);
- Crash(NULL);
- break;
- }
- break;
-
- case EI_iCLOSEWINDOW:
- ReplyMsg(msg);
- Crash(NULL);
- break;
-
- case EI_iACTIVEWINDOW:
- E_SetRGB8CM(window->WScreen->EScreen, screencolors, 0, MAXCOL);
- break;
-
- case EI_iINACTIVEWINDOW:
- E_SetRGB8CM(window->WScreen->EScreen, oldscreencolors, 0, MAXCOL);
- break;
-
- default:
- printf("You don't really ever want to see this.\n");
- break;
- }
- ReplyMsg((struct Message *)msg);
- }
- }
- }
-
-
-
- /* Function to display the interpretation immediately */
-
- static void
- func_disp(ftype, frame, buf, srcx, srcy, destx, desty, swidth, sheight)
- int ftype;
- int frame;
- unsigned char *buf;
- int srcx, srcy;
- int destx, desty;
- int swidth, sheight;
- {
- static int colchange=0; /* Colormap has changed */
-
- switch (ftype)
- {
- case FLI_COPY:
- case FLI_LC:
- case FLI_DELTA:
- case FLI_BRUN:
- EG_CopyBitMapRastPort(map, rp, srcx, srcy, swidth, sheight, destx, desty);
- break;
-
- case FLI_BLACK:
- EG_SetAPen(rp, 0x00000000);
- EG_RectFill(rp, destx, desty, swidth, sheight);
- break;
-
- case FLI_COLOR:
- while(srcy--)
- {
- screencolors[srcx].Red = ((*(buf++) & 0x3f) << 2);
- screencolors[srcx].Green = ((*(buf++) & 0x3f) << 2);
- screencolors[srcx].Blue = ((*(buf++) & 0x3f) << 2);
- srcx++;
- }
- colchange = 1;
- break;
-
- case FLI_256_COLOR:
- while(srcy--)
- {
- screencolors[srcx].Red = ((*(buf++) & 0xff));
- screencolors[srcx].Green = ((*(buf++) & 0xff));
- screencolors[srcx].Blue = ((*(buf++) & 0xff));
- srcx++;
- }
- colchange = 1;
- break;
-
- case FLI_SYNC:
- if (colchange)
- {
- E_SetRGB8CM(window->WScreen->EScreen, screencolors, 0, MAXCOL);
- colchange = 0;
- }
-
- check_key();
-
- /* Do we have a delay between the frames? */
- if (jiffies)
- Delay(jiffies);
-
- break;
- }
- }
-
-
-
- /* Store the interpretation */
-
- static void
- func_interp(ftype, frame, buf, srcx, srcy, destx, desty, swidth, sheight)
- int ftype; /* The type of this chunk */
- int frame; /* The number of this frame */
- unsigned char *buf; /* A pointer to the pixel/colormap data */
- int srcx, srcy; /* The upper left corner in the data array */
- int destx, desty; /* The upper left corner in the window */
- int swidth, sheight; /* The dimensions of the rectangle */
- {
- XColor *coltmp; /* Temporary storage for pointer to XColor struct */
-
- /* set title of EGS window to current frame number */
- char framenum[20];
- sprintf(framenum, "load: frame %d", disp_cur->disp_frame);
- EI_SetWindowTitles(window, framenum, (char *)-1);
-
- /* Allocate another element in the display list */
- disp_cur->disp_next = (struct disp_list *)malloc(sizeof(struct disp_list));
- disp_cur = disp_cur->disp_next;
-
- /* Clear the pointer to the next element so we find the end of the list */
- disp_cur->disp_next = (struct disp_list *)0;
-
- /* Copy info pertaining to all or most of the chunks */
- disp_cur->disp_type = ftype;
- disp_cur->disp_frame = frame;
- disp_cur->disp_width = swidth;
- disp_cur->disp_height = sheight;
- disp_cur->disp_destx = destx;
- disp_cur->disp_desty = desty;
- disp_cur->disp_pix = (E_EBitMapPtr)NULL;
-
- switch (ftype)
- {
- case FLI_COPY:
- case FLI_LC:
- case FLI_DELTA:
- case FLI_BRUN:
- disp_cur->disp_pix = E_AllocBitMap(wwidth, wheight, 8, E_PIXELMAP, 0, 0);
- if (disp_cur->disp_pix == NULL)
- Crash("could not allocate memory for picture");
- disp_cur->disp_pix->Lock++;
-
- EB_CopyBitMap(map, disp_cur->disp_pix, srcx, srcy, swidth, sheight, 0, 0, 0);
- break;
-
- case FLI_COLOR:
- /* Create an array of XColor to hold the colors. Specific to FLI_COLOR:
- srcx is the starting color index and srcy is the number of colors */
-
- coltmp = (XColor *)malloc(srcy * sizeof(XColor));
- disp_cur->disp_cols = coltmp;
- disp_cur->disp_numcol = srcy;
-
- /* Copy the changed colors to the XColor array */
- while(srcy--)
- {
- coltmp->red = ((*(buf++) & 0x3f) << 2);
- coltmp->green = ((*(buf++) & 0x3f) << 2);
- coltmp->blue = ((*(buf++) & 0x3f) << 2);
- coltmp->pixel = srcx++;
- coltmp++;
- }
- break;
-
- case FLI_256_COLOR:
- /* Create an array of XColor to hold the colors. Specific to FLI_256_COLOR:
- srcx is the starting color index and srcy is the number of colors */
- coltmp = (XColor *)malloc(srcy * sizeof(XColor));
- disp_cur->disp_cols = coltmp;
- disp_cur->disp_numcol = srcy;
-
- /* Copy the changed colors to the XColor array */
- while(srcy--)
- {
- coltmp->red = ((*(buf++) & 0xff));
- coltmp->green = ((*(buf++) & 0xff));
- coltmp->blue = ((*(buf++) & 0xff));
- coltmp->pixel = srcx++;
- coltmp++;
- }
- break;
-
- /* FLI_BLACK and FLI_SYNC only need to be stored */
- case FLI_BLACK:
- case FLI_SYNC:
- break;
- }
-
- }
-
-
- /* Display the stored interpretation */
-
- static void
- display_interp(dc)
- struct disp_list *dc; /* The structure holding the info on the chunk */
- {
- static int colchange=0; /* Colormap has changed */
- int idx, pixel, numcols;
- int swidth, sheight; /* Dimension of the changing rectangle */
- int destx, desty; /* Upper left corner of the rectangle */
-
- /* Copy some fields from the structure */
- swidth = dc->disp_width;
- sheight = dc->disp_height;
- destx = dc->disp_destx;
- desty = dc->disp_desty;
-
- switch (dc->disp_type)
- {
- case FLI_COPY:
- case FLI_LC:
- case FLI_DELTA:
- case FLI_BRUN:
- EG_CopyBitMapRastPort(dc->disp_pix, rp, 0, 0, swidth, sheight, destx, desty);
- break;
-
- case FLI_BLACK:
- /* Clear the whole rectangle */
- EG_SetAPen(rp, 0x00000000);
- EG_RectFill(rp, destx, desty, swidth, sheight);
- break;
-
- case FLI_COLOR:
- case FLI_256_COLOR:
- /* Store the changed colors in the colormap and note that */
- idx = 0;
- numcols = dc->disp_numcol;
- while(numcols--)
- {
- pixel = dc->disp_cols[idx].pixel;
- screencolors[pixel].Red = dc->disp_cols[idx].red;
- screencolors[pixel].Green = dc->disp_cols[idx].green;
- screencolors[pixel].Blue = dc->disp_cols[idx].blue;
- idx++;
- }
- colchange = 1;
- break;
-
- case FLI_SYNC:
- /* If the colors have changed we set the colormap for the window */
- if (colchange)
- {
- E_SetRGB8CM(window->WScreen->EScreen, screencolors, 0, MAXCOL);
- colchange = 0;
- }
-
- check_key();
-
- if (jiffies)
- Delay(jiffies);
-
- break;
- }
- }
-
-
- /* Draw a given string to the center of the window */
-
- static void
- text_center(str)
- char *str;
- {
- int w;
-
- EG_SetAPen(rp, 0x00000000);
- EG_RectFill(rp, 0, 0, wwidth, wheight);
-
- /* Determine the width of the string */
- w = EG_TextLength(rp, str, strlen(str));
- if (w > wwidth)
- w = wwidth;
-
- /* And draw the string */
- EG_SetAPen(rp, 0xffffff00);
- EG_Move(rp, (wwidth-w)/2, wheight/2);
- EG_Text(rp, str, strlen(str));
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int fd; /* For the main file descriptor */
- struct fli_header header; /* To hold the main header */
- unsigned char *data; /* Always has the current image data */
- int repeatcount; /* How many times to loop */
- unsigned char notfirst; /* Is this not the first time through? */
- char *fname; /* Pointer to filename */
- int depth; /* depth of (EGS default) screen */
- unsigned char *mode; /* for env.-variable */
-
- fdelay = -1;
- repeatcount = 10;
-
- /* required very early for (possible) error handling */
- disp_root.disp_next = (struct disp_list *)0;
-
- while (--argc && argv[1][0] == '-')
- {
- argv++;
- switch (argv[0][1])
- {
- case 'r':
- repeatcount = atol(&(argv[0][2]));
- break;
- case 'd':
- fdelay = atol(&(argv[0][2]));
- break;
- case 'n':
- flag_noint = 1;
- break;
- case 'v':
- verbose = 1;
- break;
- default:
- usage();
- }
-
- }
-
- if (argc != 1)
- usage();
-
- fname = argv[1];
- strcpy(fliname, argv[1]);
-
- fd = open(fname, 0);
- if (fd < 0)
- {
- (void) fprintf(stderr, "Error opening %s.\n", fname);
- perror("EGSFlick");
- exit(1);
- }
-
- /* Read the main FLI header */
- read_flihead(fd, &header);
-
- if (((header.fhd_magic & 0x0000ffff) != FLI_MAGIC) &&
- ((header.fhd_magic & 0x0000ffff) != FLC_MAGIC))
- {
- (void) fprintf(stderr, "%s, not a .fli file.\n", fname);
- exit(0);
- }
-
- /* Get the width and height */
-
- wwidth = header.fhd_width;
- wheight = header.fhd_height;
-
- /* The speed is stored in 1/70 seconds, convert to usecs */
- if (fdelay < 0)
- fdelay = header.fhd_speed;
-
- convert_fdelay();
-
- /* open the required EGS libraries */
- EGSBase = OpenLibrary("egs.library", 0);
- if (NULL == EGSBase)
- Crash ("couldn't open 'egs.library' -- stop.");
-
- EGSBlitBase = OpenLibrary("egsblit.library", 0);
- if (NULL == EGSBlitBase)
- Crash ("couldn't open 'egsblit.library' -- stop.");
-
- EGSIntuiBase = OpenLibrary("egsintui.library", 0);
- if (NULL == EGSIntuiBase)
- Crash ("couldn't open 'egsintui.library' -- stop.");
-
- EGSGfxBase = OpenLibrary("egsgfx.library", 0);
- if (NULL == EGSGfxBase)
- Crash ("couldn't open 'egsgfx.library' -- stop.");
-
- /*
- try to read environment variable 'EGSFLICK' - if set, use its
- value as the screen mode name and force the window to open
- on that screen instead of the EGS default screen
- */
- mode = getenv("EGSFLICK");
- if (mode != NULL)
- {
- /* EGSFLICK = "default" ? */
- if (stricmp(mode, "default") != 0)
- {
- newscreen.Mode = mode;
- screen = EI_OpenScreen(&newscreen);
- if (screen == NULL)
- Crash("Could not open EI_Screen");
- newWindow.Screen = screen;
- }
- }
-
- /*
- open EGS window on the default screen, hoping that it's currently set
- to 8 bit
- */
-
- /* Create a wwidth x wheight window to show the flick */
- newWindow.Width = wwidth;
- newWindow.Height = wheight;
- window = EI_OpenWindow(&newWindow);
- if (window == NULL)
- Crash("Couldn't open EGS window -- stop.");
-
- /* save current color table */
- E_GetRGB8CM(window->WScreen->EScreen, oldscreencolors, 0, MAXCOL);
- E_GetRGB8CM(window->WScreen->EScreen, screencolors, 0, MAXCOL);
-
- /* check if the EGS default screen is really an 8 bit screen - if not, exit */
- depth = window->WScreen->EScreen->Map->Depth;
-
- #if 0
- /* This is the 'old' test - doesn't work on a Spectrum, however, so I removed it for now.. */
- if ((window->WScreen->EScreen->Map->Depth != 8) ||
- (window->WScreen->EScreen->Map->Type != E_PIXELMAP))
- #endif
-
- if (window->WScreen->EScreen->Map->Depth != 8)
- Crash("Screen has a wrong depth - we need an 8 bit chunky pixel screen.");
-
- /* for faster access to this structure...*/
- rp = window->RPort;
-
- /* now allocate memory for the image via EGS */
- map = E_AllocBitMap(wwidth, wheight, 8, E_PIXELMAP, 0, 0);
- if (map == NULL)
- Crash("could not allocate memory for off-screen bitmap");
-
- /* increase lock counter on map so it doesn't get mapped away */
- map->Lock++;
-
- /* old version... data = map->Typekey.PixelMap.Planes.Dest; */
- data = map->Plane;
-
- notfirst = 0;
-
- /* Either interpret the file while displaying it */
-
- if (flag_noint)
- {
- EI_SetWindowTitles(window, fliname, (char *)-1);
- if (repeatcount)
- {
- while (repeatcount--)
- {
- interpret_fli(fd, &header, data, notfirst, func_disp);
- notfirst = 1;
- }
- }
- else
- {
- for(;;)
- {
- interpret_fli(fd, &header, data, notfirst, func_disp);
- notfirst = 1;
- }
- }
- }
-
- /* Or interpret everything first and display it afterwards */
- else
- {
- text_center("Please wait while loading the animation");
-
- /* Interpret it and store the results */
- disp_cur = &disp_root;
- interpret_fli(fd, &header, data, 0, func_interp);
-
- /* Now display the results */
- EI_SetWindowTitles(window, fliname, (char *)-1);
-
- if (repeatcount)
- {
- while (repeatcount--)
- {
- disp_cur = &disp_root;
- while (disp_cur->disp_next)
- {
- disp_cur = disp_cur->disp_next;
-
- /* Only display the first frame once */
- if (disp_cur->disp_frame || !notfirst)
- display_interp(disp_cur);
- }
- notfirst = 1;
- }
- }
- else
- {
- for (;;)
- {
- disp_cur = &disp_root;
- while (disp_cur->disp_next)
- {
- disp_cur = disp_cur->disp_next;
-
- /* Only display the first frame once */
- if (disp_cur->disp_frame || !notfirst)
- display_interp(disp_cur);
- }
- notfirst = 1;
- }
- }
- }
-
- Crash(NULL);
- }
-
-
- void Crash (char *string)
- {
- /* free bitmaps in display list */
- disp_cur = &disp_root;
- while (disp_cur->disp_next)
- {
- disp_cur = disp_cur->disp_next;
- if (disp_cur->disp_pix)
- {
- disp_cur->disp_pix->Lock--;
- E_DisposeBitMap(disp_cur->disp_pix);
- }
- }
-
- if (window)
- {
- /* restore original color map (only if window was opened before) */
- E_SetRGB8CM(window->WScreen->EScreen, oldscreencolors, 0, MAXCOL);
- }
-
- if (map)
- {
- map->Lock--;
- E_DisposeBitMap(map);
- }
- if (window)
- EI_CloseWindow(window);
-
- if (screen)
- EI_CloseScreen(screen);
-
- if (EGSBase)
- CloseLibrary(EGSBase);
- if (EGSBlitBase)
- CloseLibrary(EGSBlitBase);
- if (EGSIntuiBase)
- CloseLibrary(EGSIntuiBase);
- if (EGSGfxBase)
- CloseLibrary(EGSGfxBase);
- if (NULL == string)
- exit (0);
- else
- {
- printf ("%s.\n", string);
- exit (10);
- }
- }
-
-